/**
 *  EKology - An Ecosystem Simulation Framework
 *  Copyright (C) 2008  Aarón Tavío - aaron.tavio at gmail.com - ULPGC
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package net.ekology.ekosystem.datatypes;

import java.io.Serializable;


/**
 * @author Aarón Tavío - aaron.tavio at gmail.com
 * @version 1.0.0 - 20081019-1700
 */
public class EKVector implements Cloneable, Serializable {
    protected double[] aComponent;
    
    
    public EKVector(double[] aComponent) {
        this.aComponent = (double []) aComponent.clone();
    }
    
    public EKVector(EKVector oEKVector) {
        aComponent = oEKVector.getComponents();
        aComponent = (double []) aComponent.clone();
    }
    
    public EKVector(double x, double y) {
        aComponent = new double[2];
        aComponent[0] = x;
        aComponent[1] = y;
    }
    
    
    public EKVector(EKVector oDirection, double dModulus) {
        double dAngle;
        
        dAngle = oDirection.getRotationAngle();
        
        aComponent = new double[2];
        aComponent[0] = Math.cos(dAngle)*dModulus;
        aComponent[1] = Math.sin(dAngle)*dModulus;
    }
    
            
    public int getNumComponents() {
        return this.aComponent.length;
    }
    
    public double[] getComponents() {
        return (double []) this.aComponent.clone();
    }
    
    public double getComponent(int iPos) {
        return this.aComponent[iPos];
    }
    
    public double getRotationAngle() {
        double x,y,dResult;
        
        x = this.aComponent[0];
        y = this.aComponent[1];
        
        if (x==0) {
            if (y==0) dResult = 0;
            else dResult = (y>0)? Math.PI/2 : -Math.PI/2;
        } else {
            dResult = Math.atan(y/x);
            if (x < 0) dResult += Math.PI;
        }
        
        return dResult;
    }
    
    
    public double getDirection() {
        return getRotationAngle()-Math.PI/2;
    }
    
    
    public EKVector normalize() {
        double dModule = module();
        
        for(int i=0; i < aComponent.length; i++) aComponent[i] /= dModule;
            
        return this;
    }
    
    public double length() {
        return module();
    }
    
    public double module() {
        double dResult = 0;
        
        for(double dElem: aComponent) dResult += dElem*dElem;
        
        return Math.sqrt(dResult);
    }
    
    public boolean equals(EKVector oVector) {
        boolean bResult = true;
        
        if (this.getNumComponents() == oVector.getNumComponents()) {
            for (int i=0; i<aComponent.length; i++) {
                if (aComponent[i] != oVector.getComponent(i)) {
                    bResult = false;
                    break;
                }
            }
            
        }
        else bResult = false;
        
        return bResult;
    }
    
    
    public void setRotationAngle(double dRotationAngle) {
        double dModulus;
        
        dModulus = this.module();

        aComponent[0] = Math.cos(dRotationAngle)*dModulus;
        aComponent[1] = Math.sin(dRotationAngle)*dModulus;
    }
    
    
    public EKVector add(EKVector oEKVector) {
        double[] aComponent = oEKVector.getComponents();
        
        if (this.aComponent.length == aComponent.length) {
            for(int i=0; i < aComponent.length; i++) this.aComponent[i] += aComponent[i];
        }
        
        return this;
    }
    
    public EKVector sub(EKVector oEKVector) {
        double[] aComponent = oEKVector.getComponents();
        
        if (this.aComponent.length == aComponent.length) {
            for(int i=0; i < aComponent.length; i++) this.aComponent[i] -= aComponent[i];
        }
        
        return this;
    }
    
    
    @Override
    public String toString() {
        String sResult = "{ aComponent: [";
        
        for (int i=0; i<aComponent.length-1; i++) sResult += String.format("%.2f, ", aComponent[i]);
        
        sResult += String.format("%.2f]}",aComponent[(aComponent.length-1)]);
        
        return sResult;
    }
    
    
    @Override
    public EKVector clone() {
        return new EKVector(this.aComponent);
    }
}
